package com.mobile.service.impl.system;

import com.github.pagehelper.PageInfo;
//import com.mobile.service.convert.RoleConverter;
import com.mobile.service.convert.RoleConverter;
import com.mobile.service.dao.DaoSupport;
import com.mobile.service.dto.RoleDTO;
import com.mobile.service.dto.RoleQueryDTO;
import com.mobile.service.entity.Role;
import com.mobile.service.inter.system.RoleService;
import com.mobile.service.util.PageUtils;
import com.mobile.util.*;
import com.mobile.util.config.aop.AutoFill;
import com.mobile.util.config.aop.OperateType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import redis.clients.jedis.Jedis;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 角色管理service实现类
 */
@Transactional
@Service("roleService")
public class RoleServiceImpl implements RoleService {
    @Resource(name = "daoSupport")
    private DaoSupport dao;
    @Autowired
    private RoleConverter roleConverter;


    /**
     * 分页查询角色列表
     */
    @SuppressWarnings("unchecked")
    @Override
    public PageResult<RoleDTO> getRoleListPage(RoleQueryDTO queryDTO) throws Exception {
        PageUtils.startPage(queryDTO);
        List<RoleDTO> list = (List<RoleDTO>) dao.findForList("RoleMapper.rolelistPage", queryDTO);
        PageUtils.clearPage();
        return new PageResult<>(list);
    }

    /**
     * 根据id查询角色详情
     */
    @Override
    public RoleDTO getRoleById(Integer id) throws Exception {
        RoleDTO role = (RoleDTO) dao.findForObject("RoleMapper.getRoleById", id);
        if (role == null) {
            return null;
        }

        // 查询角色分配的权限
        List<String> auths = (List<String>) dao.findForList("RoleMapper.getRoleAuthByRoleId", id);
        role.setAuths(auths);

        // 查询功能权限树
        role.setTreeData(this.getAuthTree());
        return role;
    }

    /**
     * 新增角色&分配权限
     */
    @Override
    public Map<String, Object> addRole(RoleDTO roleDTO) throws Exception {
        Map<String, Object> map = new HashMap<>();

        // 检查角色名称唯一性
        int nameExists = (int) dao.findForObject("RoleMapper.checkRoleExistsByName", roleDTO.getRoleName());
        if (nameExists > 0) {
            return failedResult(map, "E0004", "该角色名称");
        }

        // 检查角色代号唯一性
        int codeExists = (int) dao.findForObject("RoleMapper.checkRoleExistsByCode", roleDTO.getRoleCode());
        if (codeExists > 0) {
            return failedResult(map, "E0004", "该角色代号");
        }
        Role role = roleConverter.toEntity(roleDTO);
        dao.save("RoleMapper.insertRole",role );
        // 分配权限
        roleDTO.setRoleId(role.getRoleId());
        assignRoleAuths(roleDTO);

        return successResult(map, "I0011");
    }

    /**
     * 修改角色&权限
     */
    @Override
    public Map<String, Object> updateRole(RoleDTO roleDTO, Jedis jedis) throws Exception {
        Map<String, Object> map = new HashMap<>();

        // 校验角色存在性
        RoleDTO existRole = (RoleDTO) dao.findForObject("RoleMapper.getRoleById", roleDTO.getRoleId());
        if (existRole == null) {
            return failedResult(map, "E0001");
        }

        // 检查角色名称冲突
        RoleDTO sameNameRole = (RoleDTO) dao.findForObject("RoleMapper.getRoleByName", roleDTO.getRoleName());
        if (sameNameRole != null && !sameNameRole.getRoleId().equals(roleDTO.getRoleId())) {
            return failedResult(map, "E0004", "该角色名称");
        }

        dao.update("RoleMapper.updateRole", roleDTO);
        // 重新分配权限
        reassignRoleAuths(roleDTO);

        return successResult(map, "I0009");
    }

    /**
     * 删除角色
     */
    @Override
    public Map<String, Object> removeRole(Integer roleId) throws Exception {
        Map<String, Object> map = new HashMap<>();

        // 检查角色是否被使用
        int userCount = (int) dao.findForObject("RoleMapper.checkUserRoleExists", roleId);
        if (userCount > 0) {
            return failedResult(map, "E0056");
        }

        dao.delete("RoleMapper.deleteRole", roleId);
        dao.delete("RoleMapper.deleteRoleAuth", roleId);
        return successResult(map, "I0010");
    }

    /**
     * 获取所有角色（下拉框）
     */
    @Override
    public List<PageData> getAllRoleList(PageData userRole) throws Exception {
        RoleDTO role = (RoleDTO) dao.findForObject("RoleMapper.getRoleById", userRole.get("user_role"));
        if (role == null) return new ArrayList<>();

        String roleCode = role.getRoleCode();
        if (!Const.ROLE_ADMIN.equals(roleCode)) {
            List<PageData> roles = (List<PageData>) dao.findForList("RoleMapper.getRoleByCode", roleCode);
            return roles;
        }
        return (List<PageData>) dao.findForList("RoleMapper.getRoleByCode", null);
    }

    //=== 私有工具方法 ===//

    private Map<String, Object> successResult(Map<String, Object> map, String msgCode) {
        map.put(Const.ACTION_RESULT, Const.ACTION_RESULT_SUCCESS);
        map.put(Const.ACTION_MESSAGE, MessageUtil.getMessage(msgCode));
        return map;
    }

    private Map<String, Object> failedResult(Map<String, Object> map, String msgCode, String params) {
        map.put(Const.ACTION_RESULT, Const.ACTION_RESULT_FAILED);
        map.put(Const.ACTION_MESSAGE, MessageUtil.getMessage(msgCode, params));
        return map;
    }
    private Map<String, Object> failedResult(Map<String, Object> map, String msgCode) {
        map.put(Const.ACTION_RESULT, Const.ACTION_RESULT_FAILED);
        map.put(Const.ACTION_MESSAGE, MessageUtil.getMessage(msgCode));
        return map;
    }
    /**
     * 分配角色权限
     */
    private void assignRoleAuths(RoleDTO roleDTO) throws Exception {
        List<PageData> authList = new ArrayList<>();
        buildRoleAuthRelations(
                this.getAuthTree(),
                roleDTO.getRoleId(),
                roleDTO.getCreateUser(),
                authList,
                roleDTO.getAuths()
        );
        dao.save("RoleMapper.insertRoleAuth", authList);
    }

    /**
     * 重新分配角色权限
     */
    private void reassignRoleAuths(RoleDTO roleDTO) throws Exception {
        Integer roleId = roleDTO.getRoleId();
        String userCode = roleDTO.getUpdateUser();

        // 获取新旧权限对比差异
        List<PageData> oldAuths = (List<PageData>)
                dao.findForList("RoleMapper.getRoleAuthByRoleIdNoConcat", roleId);
        List<PageData> newAuths = new ArrayList<>();
        buildRoleAuthRelations(
                this.getAuthTree(),
                roleId,
                userCode,
                newAuths,
                roleDTO.getAuths()
        );

        // 计算需要更新的权限
        List<PageData> updates = calculateAuthUpdates(oldAuths, newAuths, roleId, userCode);

        // 批量更新用户权限
        if (!updates.isEmpty()) {
            dao.delete("RoleMapper.deleteUserAuthBatch", updates);
            List<PageData> userAuths = buildUserAuthUpdates(
                    (List<String>) dao.findForList("RoleMapper.getUserCodeByRoleId", roleId),
                    updates
            );
            if (!userAuths.isEmpty()) {
                dao.batchSave("UserMapper.addUserAuth", userAuths);
            }
        }

        // 更新角色权限
        dao.delete("RoleMapper.deleteRoleAuth", roleId);
        dao.save("RoleMapper.insertRoleAuth", newAuths);
    }

    /**
     * 构建权限关系
     */
    private void buildRoleAuthRelations(
            List<PageData> authTree,
            Integer roleId,
            String userCode,
            List<PageData> authList,
            List<String> selectAuth) {

        for (PageData node : authTree) {
            List<PageData> children = (List<PageData>) node.get("children");
            if (children == null || children.isEmpty()) {
                String key = (String) node.get("key");
                String[] parts = key.split("-");
                PageData auth = new PageData();
                auth.put("roleId", roleId);
                auth.put("functionId", parts[0]);
                auth.put("authId", parts[1]);
                auth.put("isAuth", selectAuth.contains(key) ? "1" : "0");
                auth.put("createUser", userCode);
                auth.put("updateUser", userCode);
                authList.add(auth);
            } else {
                buildRoleAuthRelations(children, roleId, userCode, authList, selectAuth);
            }
        }
    }

    /**
     * 计算权限变更
     */
    private List<PageData> calculateAuthUpdates(
            List<PageData> oldAuths,
            List<PageData> newAuths,
            Integer roleId,
            String userCode) {

        List<PageData> updates = new ArrayList<>();

        // 检测被移除的权限
        for (PageData oldAuth : oldAuths) {
            String funcId = oldAuth.get("function_id").toString();
            String authId = oldAuth.get("auth_id").toString();
            boolean exists = newAuths.stream()
                    .anyMatch(a ->
                            a.get("functionId").equals(funcId) &&
                                    a.get("authId").equals(authId) &&
                                    "1".equals(a.get("isAuth"))
                    );

            if (!exists) {
                updates.add(createAuthUpdate(roleId, funcId, authId, "0", userCode));
            }
        }

        // 检测新增的权限
        for (PageData newAuth : newAuths) {
            if (!"1".equals(newAuth.get("isAuth"))) continue;

            String funcId = newAuth.get("functionId").toString();
            String authId = newAuth.get("authId").toString();
            boolean exists = oldAuths.stream()
                    .anyMatch(a ->
                            a.get("function_id").toString().equals(funcId) &&
                                    a.get("auth_id").toString().equals(authId)
                    );

            if (!exists) {
                updates.add(createAuthUpdate(roleId, funcId, authId, "1", userCode));
            }
        }

        return updates;
    }

    private PageData createAuthUpdate(
            Integer roleId, String funcId, String authId, String isAuth, String userCode) {
        PageData update =   new PageData();
        update.put("roleId", roleId);
        update.put("functionId", funcId);
        update.put("authId", authId);
        update.put("isAuth", isAuth);
        update.put("userCode", userCode);
        return update;
    }

    /**
     * 构建用户权限更新数据
     */
    private List<PageData> buildUserAuthUpdates(
            List<String> userCodes,
            List<PageData> updates) {

        List<PageData> userAuths = new ArrayList<>();
        for (String userCode : userCodes) {
            for (PageData update : updates) {
                PageData userAuth = new PageData();
                userAuth.put("userCode", userCode);
                userAuth.put("functionId", update.get("functionId"));
                userAuth.put("authId", update.get("authId"));
                userAuth.put("roleId", update.get("roleId"));
                userAuth.put("isAuth", update.get("isAuth"));
                userAuth.put("createUser", update.get("userCode"));
                userAuth.put("updateUser", update.get("userCode"));
                userAuths.add(userAuth);
            }
        }
        return userAuths;
    }

    /**
     * 获取功能权限树
     */
    @Override
    public List<PageData> getAuthTree() throws Exception {
        List<PageData> authList = (List<PageData>)
                dao.findForList("AuthMapper.authListAll");
        return buildAuthTree("0", authList);
    }

    /**
     * 递归构建权限树
     */
    private List<PageData> buildAuthTree(String parentId, List<PageData> allAuths) throws Exception {
        List<PageData> nodes = (List<PageData>)
                dao.findForList("RoleMapper.getMenuByParentId", parentId);

        for (PageData node : nodes) {
            String nodeId = (String) node.get("key");
            List<PageData> children = buildAuthTree(nodeId, allAuths);

            if (children.isEmpty()) {
                node.put("children", buildLeafAuths(nodeId, allAuths));
            } else {
                node.put("children", children);
            }
        }
        return nodes;
    }

    /**
     * 构建叶子节点权限
     */
    private List<PageData> buildLeafAuths(String menuId, List<PageData> allAuths) {
        List<PageData> leafAuths = new ArrayList<>();
        for (PageData auth : allAuths) {
            PageData leaf = new PageData();
            leaf.put("key", menuId + "-" + auth.get("key"));
            leaf.put("title", auth.get("title"));
            leaf.put("isAuth", "0");
            leafAuths.add(leaf);
        }
        return leafAuths;
    }

    /**
     * 根据角色代号查询
     */
    @Override
    public List<RoleDTO> getRoleByCode(String roleCode) throws Exception {
        return (List<RoleDTO>) dao.findForList("RoleMapper.getRoleByCode", roleCode);
    }
}